# -*- coding: utf-8 -*-

from decimal import Decimal

from sqlalchemy import func

from common.bankcard.model import Bankcard
from common.transaction.model import *
from common.utils import exceptions as err
from common.utils import track_logging
from common.utils.db import list_object
from common.utils.db import paginate
from common.utils.decorator import sql_wrapper

_LOGGER = track_logging.getLogger(__name__)


@sql_wrapper
def create_manual_trans(params):
    try:
        manual_trans = Transaction()
        for k, v in params.iteritems():
            setattr(manual_trans, k, v)
        manual_trans.trans_type = TRANS_TYPE.MANUAL
        manual_trans.rollbacked = 0
        manual_trans.save(auto_commit=False)

        # 源卡余额调整
        source_card = Bankcard.query.filter(
            Bankcard.id == params['card_id']).first()
        if params['target_type'] in [TRANS_TARGET_TYPE.EXTERNAL_OUT, TRANS_TARGET_TYPE.INTERNAL_OUT]:
            source_card.calculate_balance -= Decimal("%.15g" % float(params['amount']))
            source_card.calculate_balance -= Decimal("%.15g" % float(params.get('addition_amount', 0)))
        elif params['target_type'] == TRANS_TARGET_TYPE.EXTERNAL_IN:
            # 此类情况addition_amount无意义
            source_card.calculate_balance += Decimal("%.15g" % float(params['amount']))
        else:
            raise err.ParamError('target_type not valid')
        if source_card.calculate_balance < 0:
            raise err.ParamError('balance not enough')
        source_card.save(auto_commit=False)

        if params['target_type'] == TRANS_TARGET_TYPE.INTERNAL_OUT:
            # 目标卡余额调整
            target_card = Bankcard.query.filter(
                Bankcard.id == params['target_card_id']).first()
            target_card.calculate_balance += Decimal("%.15g" % float(params['amount']))
            print target_card.calculate_balance
            if target_card.calculate_balance < 0:
                raise err.ParamError('balance not enough')
            target_card.save(auto_commit=False)

        orm.session.commit()
        return manual_trans

    except Exception as e:
        orm.session.rollback()
        _LOGGER.exception('create manual trans error, %s', e)
        raise e
    finally:
        orm.session.close()


@sql_wrapper
def get_manual_trans(trans_id):
    manual_trans = Transaction.query.filter(
        Transaction.id == trans_id).filter(
        Transaction.trans_type == TRANS_TYPE.MANUAL).first()
    if not manual_trans:
        raise err.ParamError('trans id not exist')
    return manual_trans


@sql_wrapper
def update_manual_trans(trans_id, desc):
    manual_trans = Transaction.query.filter(
        Transaction.id == trans_id).filter(
        Transaction.trans_type == TRANS_TYPE.MANUAL).first()
    if not manual_trans:
        raise err.ParamError('trans id not exist')
    manual_trans.desc = desc
    manual_trans.save()
    return manual_trans


@sql_wrapper
def get_trans_by_name(tans_name):
    return Transaction.query.filter(Transaction.name == name).first()


@sql_wrapper
def list_trans(query_dct):
    query, total_count = list_object(query_dct, Transaction, disable_paginate=True)
    total_amount = query.statement.with_only_columns([func.sum(Transaction.amount)])
    total_amount = query.session.execute(total_amount).scalar()
    query = paginate(query, query_dct)
    return query.all(), total_count, total_amount
